package org.jchains.receiver;

import java.io.Serializable;
import java.security.MessageDigest;

import org.jchains.CORBA.PermissionTransferPackage.CPermission;
import org.jchains.CORBA.PermissionTransferPackage.EnvironmentEntry;
import org.jchains.CORBA.PermissionTransferPackage.Stacktrace;
import org.jchains.internal.Util;
import org.jchains.receiver.gui.PermTableModel;

public class Perm implements Serializable {

	private static final long serialVersionUID = 4711L;

	static final java.util.logging.Logger log = java.util.logging.Logger
			.getLogger("JChains");

	static final String linesep = System.getProperty("line.separator");

	long time = 0;
	String codebase = "";
	String pname = "";
	String target = "";
	String classname = "";
	String[] actions = null; // new String[] { };
	int number = -1;

	String filename;
	String methodname;
	int linenum;
	EnvironmentEntry[] m_ee = new EnvironmentEntry[] {};;

	String md5 = "";

	public Perm() {

	}

	public Perm(long _time, CPermission p, EnvironmentEntry[] ee) {
		this.time = _time;
		this.classname = p.cn.intern();
		this.codebase = p.cb.intern();
		this.pname = p.pt.intern();
		this.target = p.target.intern();
		this.actions = p.actions;
		m_ee = ee;
		Stacktrace current = getFittingStackTraceString(p.stack);
		this.filename = current.filename;
		this.methodname = current.methodname;
		this.linenum = current.linenumber;

	}

	private void normalizeName() {
		target = target.replace('\\', '/');
		if (target.indexOf('"') == -1) {
			return;
		}
		StringBuffer sb = new StringBuffer(target);
		int i = 0;
		while (i < sb.length()) {
			if (sb.charAt(i) == '"') {
				sb.insert(i, '\\');
				i++; // we do not want an endless loop
				// is there an iterator on Strings ?
			}
			i++;
		}
		target = sb.toString();
		log.info(target);
	}

	// ggf. zum Server
	private Stacktrace getFittingStackTraceString(Stacktrace[] stacktrace) {
		Stacktrace current = null;
		int stackpos = -1;
		// System.err.println("CLASS=" +
		// classname+"/stackpos before:"+stackpos);
		// int z = classname.lastIndexOf('.');
		// String package = classname.substring(0,z-1);

		for (int i = 0; i < stacktrace.length; i++) {
			if (stacktrace[i].classname.equals(classname)) {
				// System.err.println("STRIKE=" + stacktrace[i].classname);
				stackpos = i;
				break;
			} else {
				// System.err.println("STACK=" + stacktrace[i].classname);

			}

		}
		if (false) {
			System.err.println("CLASS=" + classname + "/stackpos after:"
					+ stackpos);
		}
		current = stacktrace[stackpos];
		current.classname = "";
		current.methodname = current.methodname.intern();
		current.filename = current.filename.intern();

		stacktrace = null;
		return current;
	}

	private static String concat(char del, String[] arr) {
		if (arr.length == 0) {
			return "";
		}
		StringBuffer b = new StringBuffer(100);
		for (int i = 0; i < arr.length; i++) {
			b.append(arr[i]);
			b.append(del);
		}
		b.setLength(b.length() - 1);
		return b.toString();
	}

	public String getFlatActions() {
		return concat(',', actions);
	}

	public String getMD5() {
		if (md5 == null || md5.equals("")) {
			String tmp = pname + target + getFlatActions();
			md5 = Util.getMD5forString(tmp);
		}
		return md5;
	}

	private String doReplace(String text) {

		for (int i = 0; i < m_ee.length; i++) {
			int idx = text.indexOf(m_ee[i].theValue); // regex ??
			String val = m_ee[i].theValue.trim();
			int replen = val.length();
			if (idx >= 0 && replen > 7) {
				text = text.substring(0, idx) + "${" + m_ee[i].theKey
				// + replen
						+ "}" + text.substring(idx + replen);
			}
			// text = text.replaceAll(m_ee[i].theKey,m_ee[i].theValue);
		}
		return text;
	}

	static String compstr = new String(new byte[] { (byte) 34 });

	public String getPermissionLine(boolean b) {

		if (b) {
			target = doReplace(target);
		}

		target = target.replaceAll("\"", "\\\\\"");

		StringBuffer sb = new StringBuffer(300);
		sb.append("permission ").append(pname).append(' ').append('"').append(
				target).append('"').append(' ');
		String actflat = getFlatActions();

		if (actflat.length() > 0) {

			// if (this.actions.length > 0) {
			sb.append(',').append('"').append(actflat).append('"');
		}
		;

		sb.append(';');

		sb.append("  //").append(classname);
		sb.append(",").append(this.methodname);
		sb.append(":").append(this.linenum);
		sb.append(linesep);

		return sb.toString();
	}

	public static String getLinesep() {
		return linesep;
	}

	public static java.util.logging.Logger getLog() {
		return log;
	}

	public static MessageDigest getMd() {
		return Util.md;
	}

	public String getAction() {
		return getFlatActions();
	}

	public String getCodebase() {
		return codebase;
	}

	public String getClassname() {
		return classname;
	}

	public String getMethodname() {
		return methodname;
	}

	public String getFilename() {
		return filename;
	}

	public void setClassname(String _classname) {
		this.classname = _classname;
	}

	public String getTarget() {
		return target;
	}

	public String getPname() {
		return pname;
	}

	public void setCodebase(String string) {
		codebase = string;
	}

	public void setTarget(String string) {
		target = string;
	}

	public void setPname(String string) {
		pname = string;
	}

	public long getTime() {
		return time;
	}

	public void setTime(long time) {
		this.time = time;
	}

	public String[] getActions() {
		return actions;
	}

	public void setActions(String[] actions) {
		this.actions = actions;
	}

	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}

	/*
	 * public void setCurrent(Stacktrace current) {
	 * 
	 * System.err.println("call unsupported"); System.exit(-1); }
	 * 
	 * public Stacktrace getCurrent() { System.err.println("call unsupported");
	 * System.exit(-1); return null; }
	 */

	public String getXML() {
		return "<Permission><Codebase>" + this.getCodebase() + "</Codebase>"
				+ "<Class>" + this.getClassname() + "<Class>" + "<Time>"
				+ this.getTime() + "</Time>" + "<Filename>"
				+ this.getFilename() + "</Filename>" + "<Pname>"
				+ this.getPname() + "</Pname>" + "<Target>" + this.getTarget()
				+ "</Target>" + "<Actions>" + this.getFlatActions()
				+ "</Actions>" + "<LineNumber>" + getNumber() + "</LineNumber>";

	}

	public String toString() {
		String ename = Util.shortcutEncode(target);

		return this.getTime() + ";" + this.getCodebase() + ";" + this.pname
				+ ";" + ename
				// + this.getFilename()
				+ ";" + this.getAction() + ";" + this.getMethodname() + ";"
				+ this.getClassname() + ";" + this.getNumber();

	}

	public Perm(String zeugStrings) {
		System.out.println(zeugStrings);
		String[] z = zeugStrings.split(";");
		int i = 0;
		this.time = Long.parseLong(z[i++]);
		this.codebase = z[i++];
		this.pname = z[i++];
		String ename = Util.shortDecode(z[i++]);
		this.target = ename;
		// this.filename = z[i++];
		this.actions = z[i++].split(",");
		this.methodname = z[i++];
		this.classname = z[i++];
		this.linenum = Integer.parseInt(z[i++]);

	}

	public Object[] getRowObject() {
		return new Object[] { PermTableModel.getShortTimeFromLong(getTime()),
				getCodebase(), getPname(), getTarget(), getFlatActions(),
				getClassname(), getMethodname(), getNumber() };
	}
}
